home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / ds5000.md / machCode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  68.4 KB  |  2,521 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *         C code for the mach module.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  */
  14.  
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/ds5000.md/machCode.c,v 1.11 92/08/10 17:58:30 mgbaker Exp $ SPRITE (DECWRL)";
  17. #endif not lint
  18.  
  19. #include <sprite.h>
  20. #include <stddef.h>
  21. #include <assert.h>
  22. #include <string.h>
  23.  
  24. #include <machConst.h>
  25. #include <machMon.h>
  26. #include <machInt.h>
  27. #include <mach.h>
  28. #include <sys.h>
  29. #include <sync.h>
  30. #include <dbg.h>
  31. #include <proc.h>
  32. #include <procMigrate.h>
  33. #include <procUnixStubs.h>
  34. #include <sched.h>
  35. #include <vm.h>
  36. #include <vmMach.h>
  37. #include <sig.h>
  38. #include <sigMach.h>
  39. #include <swapBuffer.h>
  40. #include <net.h>
  41. #include <timer.h>
  42. #include <ultrixSignal.h>
  43. #include <recov.h>
  44.  
  45. /*
  46.  * Conversion of function to an unsigned value.
  47.  */
  48. #define F_TO_A    (Address)(unsigned)(int (*)())
  49. /*
  50.  *  Number of processors in the system.
  51.  */
  52. #ifndef NUM_PROCESSORS
  53. #define NUM_PROCESSORS 1
  54. #endif
  55.  
  56. int mach_NumProcessors = NUM_PROCESSORS;
  57.  
  58. /*
  59.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  60.  * user mode.
  61.  */
  62. Boolean    mach_KernelMode;
  63.  
  64. /*
  65.  *  Flag used by routines to determine if they are running at
  66.  *  interrupt level.
  67.  */
  68. Boolean mach_AtInterruptLevel = FALSE;
  69.  
  70. /*
  71.  * The machine type string is imported by the file system and
  72.  * used when expanding $MACHINE in file names.
  73.  */
  74.  
  75. char *mach_MachineType = "ds5000";
  76.  
  77. extern int debugProcStubs;
  78.  
  79. /*
  80.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data
  81.  */
  82. Fmt_Format mach_Format = FMT_MIPS_FORMAT;
  83.  
  84. /*
  85.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  86.  *  to disable interrupts.  Kept on a per-processor basis.
  87.  */
  88. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  89. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  90.  
  91. /*
  92.  * The format that the kernel stack has to be in to start a process off.
  93.  */
  94. typedef struct {
  95.     int        magicNumber;        /* Magic number used to determine if
  96.                      * the stack has been corrupted. */
  97.     int        statusReg;        /* The status register value. */
  98.     int        filler[10];        /* Extra space on the stack to
  99.                      * store args and such. */
  100. } KernelStack;
  101.  
  102. /*
  103.  * The format of a signal stack that is pushed onto a user's stack when
  104.  * a signal is handled.
  105.  */
  106. typedef struct {
  107.     Sig_Stack    sigStack;
  108.     Sig_Context    sigContext;
  109. } SignalStack;
  110.  
  111. /*
  112.  * Machine dependent variables.
  113.  */
  114. Address    mach_KernStart;
  115. Address    mach_CodeStart;
  116. Address    mach_StackBottom;
  117. int    mach_KernStackSize;
  118. Address    mach_KernEnd;
  119. Address    mach_FirstUserAddr;
  120. Address    mach_LastUserAddr;
  121. Address    mach_MaxUserStackAddr;
  122. int    mach_LastUserStackPage;
  123.  
  124. char    mach_BitmapAddr[16];
  125. char    mach_BitmapLen[8];
  126.  
  127. /*
  128.  * The variables and tables below are used to dispatch kernel calls.
  129.  */
  130.  
  131. #define MAXCALLS 120
  132. #define MAXARGS  10
  133.  
  134. int machMaxSysCall;            /* Highest defined system call. */
  135. /*
  136.  * Tables to determine where to go to fetch the arguments for a system call.
  137.  */
  138. ReturnStatus (*machArgDispatch[MAXCALLS])();
  139. ReturnStatus (*machArgDispatchTable[])() = {
  140.     MachFetch0Args,
  141.     MachFetch0Args,
  142.     MachFetch0Args,
  143.     MachFetch0Args,
  144.     MachFetch0Args,
  145.     MachFetch1Arg,
  146.     MachFetch2Args,
  147.     MachFetch3Args,
  148.     MachFetch4Args,
  149.     MachFetch5Args,
  150.     MachFetch6Args,
  151. };
  152.  
  153. ReturnStatus (*(mach_NormalHandlers[MAXCALLS]))();
  154.                     /* For each system call, gives the
  155.                      * address of the routine to handle
  156.                      * the call for non-migrated processes.
  157.                      */
  158. ReturnStatus (*(mach_MigratedHandlers[MAXCALLS]))();
  159.                     /* For each system call, gives the
  160.                      * address of the routine to handle
  161.                      * the call for migrated processes. */
  162. int machKcallTableOffset;        /* Byte offset of the kcallTable field
  163.                      * in a Proc_ControlBlock. */
  164. int machStatePtrOffset;            /* Byte offset of the machStatePtr
  165.                      * field in a Proc_ControlBlock. */
  166. int machSpecialHandlingOffset;        /* Byte offset of the specialHandling
  167.                      * field in a Proc_ControlBlock. */
  168. MachStringTable    machMonBootParam;    /* Parameters from boot line. */
  169. /* 
  170.  * Pointer to the state structure for the current process and the
  171.  * current owner of the floating point unit.
  172.  */
  173. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  174. Mach_State    *machFPCurStatePtr = (Mach_State *)NIL;
  175.  
  176.  
  177. extern void PrintError _ARGS_((void));
  178. static void PrintInst _ARGS_((unsigned pc, unsigned inst));
  179. static void SoftFPReturn _ARGS_((void));
  180. static void MemErrorInterrupt _ARGS_((void));
  181. static void CheckFastRestart _ARGS_((void));
  182.  
  183. ReturnStatus    (*machInterruptRoutines[MACH_NUM_HARD_INTERRUPTS]) _ARGS_((
  184.             unsigned int statusReg, unsigned int causeReg, 
  185.             Address pc, ClientData data));
  186. void        (*machIOInterruptRoutines[MACH_NUM_IO_SLOTS]) _ARGS_((
  187.             unsigned int statusReg, unsigned int causeReg, 
  188.             Address pc, ClientData data));
  189. ClientData    machIOInterruptArgs[MACH_NUM_IO_SLOTS];
  190. ClientData    machInterruptArgs[MACH_NUM_HARD_INTERRUPTS];
  191.  
  192. extern void Mach_KernGenException();
  193. extern void Mach_UserGenException();
  194. extern void VmMach_KernTLBException();
  195. extern void VmMach_TLBModException();
  196. extern void VmMach_UTLBMiss();
  197. extern void VmMach_EndUTLBMiss();
  198.  
  199. /*
  200.  * The kernel exception handlers.
  201.  */
  202. void (*machKernExcTable[])() = {
  203.     Mach_KernGenException,
  204.     VmMach_TLBModException,
  205.     VmMach_KernTLBException,
  206.     VmMach_KernTLBException,
  207.     Mach_KernGenException,
  208.     Mach_KernGenException,
  209.     Mach_KernGenException,
  210.     Mach_KernGenException,
  211.     Mach_KernGenException,
  212.     Mach_KernGenException,
  213.     Mach_KernGenException,
  214.     Mach_KernGenException,
  215.     Mach_KernGenException,
  216. };
  217.  
  218. /*
  219.  * The kernel exception handlers.
  220.  */
  221. void (*machUserExcTable[])() = {
  222.     Mach_UserGenException,
  223.     VmMach_TLBModException,
  224.     Mach_UserGenException,
  225.     Mach_UserGenException,
  226.     Mach_UserGenException,
  227.     Mach_UserGenException,
  228.     Mach_UserGenException,
  229.     Mach_UserGenException,
  230.     MachSysCall,
  231.     Mach_UserGenException,
  232.     Mach_UserGenException,
  233.     Mach_UserGenException,
  234.     Mach_UserGenException,
  235. };
  236.  
  237. /*
  238.  * Size of the instruction and data caches.
  239.  */
  240. unsigned    machDataCacheSize;
  241. unsigned    machInstCacheSize;
  242.  
  243. /*
  244.  * The debugger structure.
  245.  */
  246. Mach_DebugState    mach_DebugState;
  247. Mach_DebugState *machDebugStatePtr = &mach_DebugState;
  248.  
  249. static void SetupSigHandler _ARGS_((register Proc_ControlBlock *procPtr, 
  250.             register SignalStack *sigStackPtr, Address pc));
  251. static void ReturnFromSigHandler _ARGS_((register Proc_ControlBlock *procPtr));
  252. static ReturnStatus Interrupt _ARGS_((unsigned statusReg, unsigned causeReg, 
  253.             Address pc));
  254. static ReturnStatus MachStdHandler _ARGS_((unsigned int statusReg, 
  255.             unsigned int causeReg, Address pc, ClientData data));
  256. static ReturnStatus MachIOInterrupt _ARGS_((unsigned int statusReg, 
  257.             unsigned int causeReg, Address pc, ClientData data));
  258. static ReturnStatus MachMemInterrupt _ARGS_((unsigned int statusReg, 
  259.             unsigned int causeReg, Address pc, ClientData data));
  260. extern ReturnStatus MachFPInterrupt _ARGS_((unsigned int statusReg, 
  261.             unsigned int causeReg, Address pc, ClientData data));
  262.  
  263. /*
  264.  * Preallocate all machine state structs.
  265.  */
  266. Mach_State    machStateTable[VMMACH_MAX_KERN_STACKS];
  267. int        nextStateIndex = 0;
  268.  
  269. /*
  270.  *  Save the bad address that caused an exception. This makes debugging
  271.  *  of TLB misses easier.
  272.  */
  273.  
  274. Address        machBadVaddr = (Address) NIL;
  275.  
  276. /*
  277.  * Set to TRUE if we are inside of Mach_Probe.
  278.  */
  279.  
  280. Boolean        machInProbe = FALSE;
  281.  
  282. /*
  283.  * Read address of Mach_Probe.
  284.  */
  285.  
  286. Address        machProbeReadAddr = (Address) NIL;
  287. typedef struct trace {
  288.     char    *srcPtr;
  289.     char    *destPtr;
  290.     int        dest1;
  291.     int        dest2;
  292.     int        src;
  293. } Trace;
  294.  
  295. extern Trace *ncopyBuffer;
  296. extern int ncopyCount;
  297. extern int ncopyPath;
  298.  
  299. /*
  300.  * Declarations of recovery-related items.  For the decstations, most
  301.  * of these are no-ops.
  302.  *
  303.  * The following two variables should be in the initialized ata space, but
  304.  * marked as not initialized.  Then , when they are updated as part of booting,
  305.  * their new values get preserved over a fast restart.
  306.  */
  307. int    storedDataSize = -1;        /* Not initialized. */
  308. char    *mach_RestartTablePtr = (char *) NIL;
  309. char    storedData[1];            /* A no-op for now. */
  310.  
  311. /*
  312.  * ----------------------------------------------------------------------------
  313.  *
  314.  * Mach_Init --
  315.  *
  316.  *    Initialize the exception vector table and some of the dispatching
  317.  *    tables.
  318.  *
  319.  * Results:
  320.  *    None.
  321.  *
  322.  * Side effects:
  323.  *    The exception vector table is initialized.
  324.  *
  325.  * ----------------------------------------------------------------------------
  326.  */
  327. void
  328. Mach_Init(boot_argc,boot_argv)
  329. int    boot_argc;    /* Argc from boot sequence. */
  330. MachStringTable    *boot_argv;    /* Boot sequence strings. */
  331. {
  332.     extern char end[], edata[];
  333.     int i;
  334.     char buf[256];
  335.     volatile unsigned int     *csrPtr = (unsigned int *) MACH_CSR_ADDR;
  336.     char    *copyPtr;
  337.  
  338.     /*
  339.      * Zero out the bss segment.
  340.      */
  341.     bzero(edata, end - edata);
  342.  
  343.     /*
  344.      * Set exported machine dependent variables.
  345.      */
  346.     mach_KernStart = (Address)MACH_KERN_START;
  347.     mach_KernEnd = (Address)MACH_KERN_END;
  348.     mach_CodeStart = (Address)MACH_CODE_START;
  349.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  350.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  351.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  352.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  353.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  354.     mach_LastUserStackPage = (MACH_MAX_USER_STACK_ADDR - 1) / VMMACH_PAGE_SIZE;
  355.  
  356.     /*
  357.      * Copy the boot parameter structure. The original location will get
  358.      * unmapped during vm initialization so we need to get our own copy.
  359.      * Depending on how the machine was booted, the boot arguments 
  360.      * may or may not be parsed.  So we'll glob them all together and
  361.      * then parse them.
  362.      */
  363.     buf[0] = '\0';
  364.     for (i = 0; i < boot_argc; i++) {
  365.     strcat(buf,boot_argv->argPtr[i]);
  366.     strcat(buf," ");
  367.     }
  368.     Mach_ArgParse(buf,&machMonBootParam);
  369.  
  370.     Mach_MonPrintf("Happy Birthday!!\n");
  371.     /*
  372.      * Get information on the memory bitmap.  This gets clobbered later.
  373.      */
  374.     /*
  375.      * IMPORTANT NOTE:  Don't use bcopy to do this, at least while
  376.      * bcopy contains the calls to Vm_CheckAccessible.  Those calls add a
  377.      * frame to the stack, causing it to overwrite the very information
  378.      * we're trying to copy.  JHH 4/18/91
  379.      */
  380.     copyPtr = Mach_MonGetenv("bitmaplen");
  381.     for(i = 0; i < sizeof(mach_BitmapLen); i++) {
  382.     mach_BitmapLen[i] = *copyPtr++;
  383.     }
  384.     copyPtr = Mach_MonGetenv("bitmap");
  385.     for(i = 0; i < sizeof(mach_BitmapAddr); i++) {
  386.     mach_BitmapAddr[i] = *copyPtr++;
  387.     }
  388.  
  389.     /*
  390.      * Set up the CSR.  Turn on memory ECC. Interrupts from IO slots are
  391.      * turned on as handlers are registered. 
  392.      */
  393.     *csrPtr = MACH_CSR_CORRECT;
  394.  
  395.  
  396.     /*
  397.      * Initialize some of the dispatching information.  The rest is
  398.      * initialized by Mach_InitSysCall below.
  399.      */
  400.     machMaxSysCall = -1;
  401.     machKcallTableOffset = (int) &((Proc_ControlBlock *) 0)->kcallTable;
  402.     machStatePtrOffset = (int) &((Proc_ControlBlock *) 0)->machStatePtr;
  403.     machSpecialHandlingOffset = (int) 
  404.                 &((Proc_ControlBlock *) 0)->specialHandling;
  405.  
  406.     /*
  407.      * We start off with interrupts disabled.
  408.      */
  409.     mach_NumDisableInterrupts[0] = 1;
  410.  
  411.     /*
  412.      * Copy down exception vector code.
  413.      */
  414.     if (F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss > 0x80) {
  415.     panic("Mach_Init: UTLB code too large\n");
  416.     }
  417.     bcopy(F_TO_A VmMach_UTLBMiss, F_TO_A MACH_UTLB_MISS_EXC_VEC,
  418.         F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss);
  419.     bcopy(F_TO_A MachException, (Address)MACH_GEN_EXC_VEC,
  420.           F_TO_A MachEndException - F_TO_A MachException);
  421.  
  422.     /*
  423.      * Set all interrupt handlers to a default, then install handlers for
  424.      * those interrupts processed by the mach module.
  425.      */
  426.     for (i = 0; i < MACH_NUM_HARD_INTERRUPTS; i++ ) {
  427.     Mach_SetHandler(i, MachStdHandler, (ClientData) i);
  428.     }
  429.     Mach_SetHandler(MACH_IO_INTR, MachIOInterrupt, (ClientData)NIL);
  430.     Mach_SetHandler(MACH_MEM_INTR, MachMemInterrupt, (ClientData)NIL);
  431.     Mach_SetHandler(MACH_FPU_INTR, MachFPInterrupt, (ClientData)NIL);
  432.  
  433.     /*
  434.      * Clear out the IO interrupt handlers.
  435.      */
  436.     for (i = 0; i < MACH_NUM_IO_SLOTS; i++ ) {
  437.     Mach_SetIOHandler(i, (void (*)()) NIL, (ClientData) NIL);
  438.     }
  439.  
  440.     if (recov_Transparent) {
  441.     CheckFastRestart();
  442.     }
  443.     /*
  444.      * Enable the memory interrupt, because we need it for Mach_Probe to
  445.      * work.  Disabling interrupts has the side-effect of enabling the
  446.      * memory interrupt.
  447.      */
  448.     Mach_DisableIntr();
  449.     /*
  450.      * Clear out the i and d caches.
  451.      */
  452.     MachConfigCache();
  453.     MachFlushCache();
  454. }
  455.  
  456. /*
  457.  * ----------------------------------------------------------------------------
  458.  *
  459.  * Mach_SetHandler --
  460.  *
  461.  *    Register an interrupt handler for R3000 interrupts.  Interrupt
  462.  *    handlers are of the form:
  463.  *
  464.  *    void
  465.  *    Handler(statusReg, causeReg, pc, data)
  466.  *        unsigned int    statusReg;    Status register.
  467.  *        unsigned int    causeReg;    Cause register.
  468.  *        Address        pc;        PC where the interrupt 
  469.  *                        occurred.
  470.  *        ClientData    data        Callback data
  471.  *    
  472.  *
  473.  * Results:
  474.  *     None.
  475.  *
  476.  * Side effects:
  477.  *     The interrupt handling table is modified.
  478.  *
  479.  * ----------------------------------------------------------------------------
  480.  */
  481.  
  482. void
  483. Mach_SetHandler(level, handler, clientData)
  484.     int level;            /* Interrupt level. */
  485.     ReturnStatus (*handler) _ARGS_((unsigned int statusReg, 
  486.                 unsigned int causeReg,
  487.                 Address pc, ClientData data)); 
  488.                     /* Interrupt handler. */
  489.     ClientData    clientData;     /* Data to pass handler. */
  490. {
  491.     /*
  492.      * Check that it is valid.  
  493.      */
  494.     if ((level < 0) || (level >= MACH_NUM_HARD_INTERRUPTS)){
  495.     panic("Warning: Bad interrupt level %d\n", level);
  496.     } else {
  497.     machInterruptRoutines[level] = handler;
  498.     machInterruptArgs[level] = clientData;
  499.     }
  500. }
  501.  
  502. /*
  503.  *----------------------------------------------------------------------
  504.  *
  505.  * MachStdHandler --
  506.  *
  507.  *    The default handler for hard interrupts.
  508.  *
  509.  * Results:
  510.  *    None.
  511.  *
  512.  * Side effects:
  513.  *    Prints out an error message.
  514.  *
  515.  *----------------------------------------------------------------------
  516.  */
  517. /*ARGSUSED*/
  518. static ReturnStatus
  519. MachStdHandler(statusReg, causeReg, pc, data)
  520.     unsigned int    statusReg;    /* Status register. */
  521.     unsigned int    causeReg;    /* Cause register. */
  522.     Address        pc;        /* PC. */
  523.     ClientData        data;        /* Interrupt level. */
  524. {
  525.     int        level;
  526.  
  527.     level = (int) data;
  528.     printf("WARNING: no handler for level %d interrupt!\n", level);
  529.     return MACH_OK;
  530. }
  531.  
  532. /*
  533.  * ----------------------------------------------------------------------------
  534.  *
  535.  * Mach_SetIOHandler --
  536.  *
  537.  *    Register an interrupt handler for IO device interrupts.  All IO
  538.  *    device interrupts are merged into the same R3000 interrupt
  539.  *    (level 0). Interrupt handlers are of the form:
  540.  *
  541.  *    void
  542.  *    Handler(data)
  543.  *        ClientData    data        Callback data
  544.  *
  545.  * Results:
  546.  *     None.
  547.  *
  548.  * Side effects:
  549.  *     The IO interrupt handling table is modified.  If the handler is not
  550.  *    NIL then the IO interrupt for the slot is turned on in the CSR.
  551.  *
  552.  * ----------------------------------------------------------------------------
  553.  */
  554.  
  555. void
  556. Mach_SetIOHandler(slot, handler, clientData)
  557.     int slot;            /* Interrupt number to set */
  558.     void (*handler) _ARGS_((ClientData data)); /* Interrupt handler. */
  559.     ClientData    clientData;     /* Data to pass handler. */
  560. {
  561.     volatile unsigned int     *csrPtr = (unsigned int *) MACH_CSR_ADDR;
  562.     unsigned int        mask;
  563.     /*
  564.      * Check that it is valid.  
  565.      */
  566.     if ((slot < 0) || (slot >= MACH_NUM_IO_SLOTS)){
  567.     panic("Warning: Bad slot number %d\n",slot);
  568.     } else {
  569.     if ((machIOInterruptRoutines[slot] != (void (*)()) NIL) &&
  570.         (handler != (void (*)()) NIL)) {
  571.         Mach_MonPrintf("WARNING: replacing existing handler for slot %d.\n",
  572.         slot);
  573.     }
  574.     machIOInterruptRoutines[slot] = handler;
  575.     machIOInterruptArgs[slot] = clientData;
  576.     if (handler != (void (*)()) NIL) {
  577.         mask = ((1 << slot) << MACH_CSR_IOINTEN_SHIFT);
  578.         if (!(mask & MACH_CSR_IOINTEN)) {
  579.         panic("Goof up computing interrupt enable bits in csr.\n");
  580.         }
  581.         *csrPtr |= mask;
  582.     }
  583.     }
  584. }
  585.  
  586. static Vm_ProcInfo    mainProcInfo;
  587. static Mach_State    mainMachState;
  588. static VmMach_ProcData    mainProcData;
  589.  
  590. /*
  591.  *----------------------------------------------------------------------
  592.  *
  593.  * Mach_InitFirstProc --
  594.  *
  595.  *    Initialize the machine state struct for the very first process.
  596.  *
  597.  * Results:
  598.  *    None.
  599.  *
  600.  * Side effects:
  601.  *    Machine info allocated and stack start set up.
  602.  *
  603.  *----------------------------------------------------------------------
  604.  */
  605. void
  606. Mach_InitFirstProc(procPtr)
  607.     Proc_ControlBlock    *procPtr;
  608. {
  609.  
  610.     assert(offsetof(Proc_ControlBlock, unixErrno) == MACH_UNIX_ERRNO_OFFSET);
  611.     procPtr->machStatePtr = &mainMachState;
  612.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  613.     procPtr->machStatePtr->kernStackEnd = 
  614.                 (mach_StackBottom + mach_KernStackSize);
  615.     /*
  616.      * Set up the TLB entries.  This code depends
  617.      * implictly upon MACH_KERN_STACK_PAGES.
  618.      */
  619.     procPtr->machStatePtr->tlbHighEntry  = 0;
  620.     procPtr->machStatePtr->tlbLowEntries[0] = 0;
  621.     procPtr->machStatePtr->tlbLowEntries[1] = 0;
  622.     procPtr->machStatePtr->tlbLowEntries[2] = 0;
  623.     procPtr->vmPtr = &mainProcInfo;
  624.     procPtr->vmPtr->machPtr = &mainProcData;
  625.     VmMach_ProcInit(&mainProcInfo);
  626.     machCurStatePtr = procPtr->machStatePtr;
  627.     VmMach_SetupContext(procPtr);
  628. }
  629.  
  630.  
  631. /*
  632.  *----------------------------------------------------------------------
  633.  *
  634.  * Mach_SetupNewState --
  635.  *
  636.  *    Initialize the machine state for this process.  This includes 
  637.  *    allocating and initializing a kernel stack.  Assumed that will
  638.  *    be called when starting a process after a fork or restarting a
  639.  *    process after a migration.
  640.  *
  641.  * Results:
  642.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  643.  *
  644.  * Side effects:
  645.  *    Machine state in the destination process control block is overwritten.
  646.  *
  647.  *----------------------------------------------------------------------
  648.  */ 
  649. ReturnStatus
  650. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  651.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  652.                      * to initialize state for. */
  653.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  654.                      * other machine on migration. */
  655.     void        (*startFunc)();    /* Function to call when process first
  656.                      * starts executing. */
  657.     Address        startPC;    /* Address to pass as argument to 
  658.                      * startFunc.  If NIL then the address
  659.                      * is taken from *fromStatePtr's 
  660.                      * exception stack. */
  661.     Boolean        user;        /* TRUE if is a user process. */
  662. {
  663.     register    KernelStack    *stackPtr;
  664.     register    Mach_State    *statePtr;
  665.     unsigned            virtPage;
  666.  
  667.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  668.     procPtr->machStatePtr = &machStateTable[nextStateIndex];
  669.     nextStateIndex++;
  670.     if (nextStateIndex >= VMMACH_MAX_KERN_STACKS) {
  671.         panic("Mach_SetupNewState: Out of machine state structs\n");
  672.     }
  673.     }
  674.  
  675.     statePtr = procPtr->machStatePtr;
  676.     /* 
  677.      * Allocate a kernel stack for this process.
  678.      */
  679.     statePtr->kernStackStart = Vm_GetKernelStack(0);
  680.     if (statePtr->kernStackStart == (Address)NIL) {
  681.     return(PROC_NO_STACKS);
  682.     }
  683.     statePtr->kernStackEnd = statePtr->kernStackStart + MACH_KERN_STACK_SIZE;
  684.     /*
  685.      * Set up the TLB entries.  This code depends
  686.      * implictly upon MACH_KERN_STACK_PAGES.
  687.      */
  688.     virtPage = (unsigned)(statePtr->kernStackStart + VMMACH_PAGE_SIZE) >>
  689.                             VMMACH_PAGE_SHIFT;
  690.     statePtr->tlbHighEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  691.                  (VMMACH_KERN_PID << VMMACH_TLB_PID_SHIFT);
  692.     virtPage -= VMMACH_VIRT_CACHED_START_PAGE;
  693.     statePtr->tlbLowEntries[0] = vmMach_KernelTLBMap[virtPage];
  694.     statePtr->tlbLowEntries[1] = vmMach_KernelTLBMap[virtPage + 1];
  695.     statePtr->tlbLowEntries[2] = vmMach_KernelTLBMap[virtPage + 2];
  696.  
  697.     statePtr->switchRegState.regs[SP] =
  698.             (unsigned)(statePtr->kernStackEnd - sizeof(KernelStack));
  699.     /*
  700.      * Initialize the stack so that it looks like it is in the middle of
  701.      * Mach_ContextSwitch.
  702.      */
  703.     stackPtr = (KernelStack *)(statePtr->switchRegState.regs[SP]);
  704.     stackPtr->magicNumber = MAGIC;
  705.     stackPtr->statusReg = 0;
  706.     statePtr->switchRegState.regs[RA] = (unsigned)startFunc;
  707.     /*
  708.      * Set up the user's stack pointer.
  709.      */
  710.     statePtr->userState.regState.regs[SP] = (unsigned)mach_MaxUserStackAddr;
  711.     /* 
  712.      * Set up the state of the process.  User processes inherit from their
  713.      * parent or the migrated process.  If the PC is not specified, take it
  714.      * from the parent as well.
  715.      */
  716.     if (user) {
  717.     bcopy((Address)&fromStatePtr->userState,
  718.           (Address)&statePtr->userState,
  719.           sizeof(statePtr->userState));
  720.     statePtr->userState.regState.pc += 4;
  721.     }
  722.     if (startPC == (Address)NIL) {
  723.     statePtr->switchRegState.regs[A0] = 
  724.             (unsigned)fromStatePtr->userState.regState.pc + 4;
  725.     } else {
  726.     statePtr->switchRegState.regs[A0] = (unsigned)startPC;
  727.     }
  728.     statePtr->userState.regState.fpStatusReg = 0;
  729.  
  730.     return(SUCCESS);
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * Mach_SetReturnVal --
  737.  *
  738.  *    Set the return value for a process from a system call.  Intended to
  739.  *    be called by the routine that starts a user process after a fork.
  740.  *
  741.  * Results:
  742.  *    None.
  743.  *
  744.  * Side effects:
  745.  *    Register D0 is set in the user registers.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */ 
  749. void
  750. Mach_SetReturnVal(procPtr, retVal, retVal2)
  751.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  752.     int            retVal;        /* Value for process to return. */
  753.     int            retVal2;    /* Second return value. */
  754. {
  755.     procPtr->machStatePtr->userState.regState.regs[V0] = (unsigned)retVal;
  756.     procPtr->machStatePtr->userState.regState.regs[V1] = (unsigned)retVal2;
  757. }
  758.  
  759. /*----------------------------------------------------------------------------
  760.  *
  761.  * Mach_Return2 --
  762.  *
  763.  *      Set the second return value for Unix compat. routines that
  764.  *      return two values.
  765.  *
  766.  * Results:
  767.  *      None.
  768.  *
  769.  * Side effects:
  770.  *      v1 <- val
  771.  *
  772.  *----------------------------------------------------------------------------
  773.  */
  774. void
  775. Mach_Return2(val)
  776. int val;
  777. {
  778.     Proc_GetActualProc()->machStatePtr->userState.regState.regs[V1] =
  779.         (unsigned)val;
  780. }
  781.  
  782. /*
  783.  *----------------------------------------------------------------------
  784.  *
  785.  * Mach_StartUserProc --
  786.  *
  787.  *    Start a user process executing for the first time.
  788.  *
  789.  * Results:
  790.  *    None.
  791.  *
  792.  * Side effects:
  793.  *    Stack pointer and the program counter set for the process and
  794.  *    the current process's image is replaced.
  795.  *
  796.  *----------------------------------------------------------------------
  797.  */
  798. void
  799. Mach_StartUserProc(procPtr, entryPoint)
  800.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  801.                      * to start. */
  802.     Address        entryPoint;    /* Where process is to start
  803.                      * executing. */
  804. {
  805.     register    Mach_State    *statePtr;
  806.  
  807.     statePtr = procPtr->machStatePtr;
  808.     statePtr->userState.regState.pc = entryPoint;
  809.     (void)MachUserReturn(procPtr);
  810.  
  811.     MachRunUserProc(entryPoint, statePtr->userState.regState.regs[SP]);
  812.     /* THIS DOES NOT RETURN */
  813. }
  814.  
  815.  
  816. /*
  817.  *----------------------------------------------------------------------
  818.  *
  819.  * Mach_ExecUserProc --
  820.  *
  821.  *    Replace the calling user process's image with a new one.
  822.  *
  823.  * Results:
  824.  *    None.
  825.  *
  826.  * Side effects:
  827.  *    Stack pointer set for the process.
  828.  *
  829.  *----------------------------------------------------------------------
  830.  */
  831. void
  832. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  833.     Proc_ControlBlock    *procPtr;        /* Process control block for
  834.                          * process to exec. */
  835.     Address        userStackPtr;    /* Stack pointer for when the
  836.                          * user process resumes 
  837.                          * execution. */
  838.     Address        entryPoint;        /* Where the user process is
  839.                          * to resume execution. */
  840. {
  841.     procPtr->machStatePtr->userState.regState.regs[SP] =
  842.                         (unsigned)userStackPtr;
  843.     Mach_StartUserProc(procPtr, entryPoint);
  844.     /* THIS DOES NOT RETURN */
  845. }
  846.  
  847. /*
  848.  *----------------------------------------------------------------------
  849.  *
  850.  * Mach_FreeState --
  851.  *
  852.  *    Free up the machine state for the given process control block.
  853.  *
  854.  * Results:
  855.  *    None.
  856.  *
  857.  * Side effects:
  858.  *    Free up the kernel stack.
  859.  *
  860.  *----------------------------------------------------------------------
  861.  */
  862. void
  863. Mach_FreeState(procPtr)
  864.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  865.                      * machine state for. */
  866. {
  867.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  868.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  869.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  870.     }
  871.     if (procPtr->machStatePtr == machFPCurStatePtr) {
  872.     machFPCurStatePtr = (Mach_State *)NIL;
  873.     }
  874. }
  875.  
  876.  
  877. /*
  878.  *----------------------------------------------------------------------
  879.  *
  880.  * Mach_CopyState --
  881.  *
  882.  *    Copy the state from the given state structure to the machine
  883.  *    state structure for the destination process control block.  Intended
  884.  *    to be used by the debugger to modify the state.The only fields
  885.  *    that can be modified are the following:
  886.  *
  887.  *        1) user stack pointer
  888.  *        2) all trap registers except for the stack pointer because the
  889.  *           stack pointer in the trap registers is the kernel stack pointer.
  890.  *        3) the PC, VOR and status register in the exception stack.
  891.  *
  892.  * Results:
  893.  *    None.
  894.  *
  895.  * Side effects:
  896.  *    Machine state in the destination process control block is overwritten.
  897.  *
  898.  *----------------------------------------------------------------------
  899.  */ 
  900. void
  901. Mach_CopyState(statePtr, destProcPtr)
  902.     Mach_State        *statePtr;    /* Pointer to state to copy from. */
  903.     Proc_ControlBlock    *destProcPtr;    /* Process control block to copy
  904.                      * state to. */
  905. {
  906.     bcopy((Address)&statePtr->userState,
  907.           (Address)&destProcPtr->machStatePtr->userState,
  908.           sizeof(statePtr->userState));
  909. }
  910.  
  911.  
  912. /*
  913.  *----------------------------------------------------------------------
  914.  *
  915.  * Mach_GetDebugState --
  916.  *
  917.  *    Extract the appropriate fields from the machine state struct
  918.  *    and store them into the debug struct.
  919.  *
  920.  * Results:
  921.  *    None.
  922.  *
  923.  * Side effects:
  924.  *    Debug struct filled in from machine state struct.
  925.  *
  926.  *----------------------------------------------------------------------
  927.  */ 
  928. void
  929. Mach_GetDebugState(procPtr, debugStatePtr)
  930.     Proc_ControlBlock    *procPtr;
  931.     Proc_DebugState    *debugStatePtr;
  932. {
  933.     register    Mach_State    *machStatePtr;
  934.  
  935.     machStatePtr = procPtr->machStatePtr;
  936.     bcopy((Address)machStatePtr->userState.regState.regs,
  937.           (Address)debugStatePtr->regState.regs,
  938.           sizeof(machStatePtr->userState.regState.regs));
  939.     debugStatePtr->regState.pc = machStatePtr->userState.regState.pc;
  940. }
  941.  
  942.  
  943. /*
  944.  *----------------------------------------------------------------------
  945.  *
  946.  * Mach_SetDebugState --
  947.  *
  948.  *    Extract the appropriate fields from the debug struct
  949.  *    and store them into the machine state struct.
  950.  *
  951.  * Results:
  952.  *    None.
  953.  *
  954.  * Side effects:
  955.  *    Machine state struct filled in from the debug state struct.
  956.  *
  957.  *----------------------------------------------------------------------
  958.  */ 
  959. void
  960. Mach_SetDebugState(procPtr, debugStatePtr)
  961.     Proc_ControlBlock    *procPtr;
  962.     Proc_DebugState    *debugStatePtr;
  963. {
  964.     register    Mach_State    *machStatePtr;
  965.  
  966.     machStatePtr = procPtr->machStatePtr;
  967.     bcopy((Address)debugStatePtr->regState.regs,
  968.           (Address)machStatePtr->userState.regState.regs,
  969.           sizeof(machStatePtr->userState.regState.regs));
  970.     machStatePtr->userState.regState.pc = debugStatePtr->regState.pc;
  971. }
  972.  
  973.  
  974. /*
  975.  * ----------------------------------------------------------------------------
  976.  *
  977.  * Mach_GetUserStackPtr --
  978.  *
  979.  *    Return the user stack pointer from the machine state struct for the
  980.  *    given process.
  981.  *
  982.  * Results:
  983.  *    The value of the user stack pointer when the process trapped.
  984.  *
  985.  * Side effects:
  986.  *    None.
  987.  *
  988.  * ----------------------------------------------------------------------------
  989.  */
  990. Address
  991. Mach_GetUserStackPtr(procPtr)
  992.     Proc_ControlBlock    *procPtr;
  993. {
  994.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  995. }
  996.  
  997.  
  998. /*
  999.  * ----------------------------------------------------------------------------
  1000.  *
  1001.  * Mach_GetStackPointer --
  1002.  *
  1003.  *    Return the value of the stack pointer.
  1004.  *
  1005.  * Results:
  1006.  *    The value of the user's stack pointer.
  1007.  *
  1008.  * Side effects:
  1009.  *    None.
  1010.  *
  1011.  * ----------------------------------------------------------------------------
  1012.  */
  1013. Address
  1014. Mach_GetStackPointer(procPtr)
  1015.     Proc_ControlBlock    *procPtr;
  1016. {
  1017.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  1018. }
  1019.  
  1020.  
  1021. /*
  1022.  *----------------------------------------------------------------------
  1023.  *
  1024.  * Mach_InitSyscall --
  1025.  *
  1026.  *    During initialization, this procedure is called once for each
  1027.  *    kernel call, in order to set up information used to dispatch
  1028.  *    the kernel call.  This procedure must be called once for each
  1029.  *    kernel call, in order starting at 0.
  1030.  *
  1031.  * Results:
  1032.  *    None.
  1033.  *
  1034.  * Side effects:
  1035.  *    Initializes the dispatch tables for the kernel call.
  1036.  *
  1037.  *----------------------------------------------------------------------
  1038.  */
  1039. void
  1040. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  1041.     int callNum;            /* Number of the system call. */
  1042.     int numArgs;            /* Number of one-word arguments passed
  1043.                      * into call on stack. */
  1044.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  1045.                      * when process isn't migrated. */
  1046.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  1047.                      * for migrated processes. */
  1048. {
  1049.     machMaxSysCall++;
  1050.     if (machMaxSysCall != callNum) {
  1051.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  1052.            callNum);
  1053.     }
  1054.     if (machMaxSysCall >= MAXCALLS) {
  1055.     printf("Warning: too many kernel calls.\n");
  1056.     machMaxSysCall--;
  1057.     return;
  1058.     }
  1059.     if (numArgs > MAXARGS) {
  1060.     printf("Warning: too many arguments to kernel call %d\n", callNum);
  1061.     numArgs = MAXARGS;
  1062.     }
  1063.     machArgDispatch[machMaxSysCall] = machArgDispatchTable[numArgs];
  1064.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  1065.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  1066. }
  1067.  
  1068.  
  1069. /*
  1070.  * ----------------------------------------------------------------------------
  1071.  *
  1072.  * MachUserExceptionHandler --
  1073.  *
  1074.  *      Handle a user exception.
  1075.  *
  1076.  * Results:
  1077.  *      TRUE if should enable the floating point coprocessor.
  1078.  *
  1079.  * Side effects:
  1080.  *      None.
  1081.  *
  1082.  * ----------------------------------------------------------------------------
  1083.  */
  1084. Boolean
  1085. MachUserExceptionHandler(statusReg, causeReg, badVaddr, pc)
  1086.     unsigned    statusReg;    /* The status register at the time of the
  1087.                  * exception. */
  1088.     unsigned    causeReg;    /* The cause register - contains the type
  1089.                  * of exception. */
  1090.     Address    badVaddr;    /* The address (if any) that the fault
  1091.                  * occured on. */
  1092.     Address    pc;        /* Program counter where to continue. */
  1093. {
  1094.     register    Proc_ControlBlock    *procPtr;
  1095.     int                    cause;
  1096.     Boolean                retVal;
  1097.     ReturnStatus            status;
  1098.  
  1099.     machBadVaddr = badVaddr;
  1100.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  1101.     if (cause != MACH_EXC_INT) {
  1102.     Mach_EnableIntr();
  1103.     }
  1104.  
  1105.     procPtr = Proc_GetActualProc();
  1106.     switch (cause) {
  1107.     case MACH_EXC_INT:
  1108.         status = Interrupt(statusReg, causeReg, pc);
  1109.         if (status != MACH_OK) {
  1110.         panic("MachUserExceptionHandler: nested interrupts.\n");
  1111.         }
  1112.         /* 
  1113.          * Enable interrupts so that we can do the user mode return
  1114.          * checks.
  1115.          */
  1116.         Mach_EnableIntr();
  1117.         break;
  1118.     case MACH_EXC_TLB_MOD:
  1119.         if (VmMach_TLBModFault(badVaddr) != SUCCESS) {
  1120.         printf("Protection fault in process %x: pc=%x addr=%x\n",
  1121.             procPtr->processID, pc, badVaddr);
  1122.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1123.                 procPtr->processID, FALSE, badVaddr);
  1124.         }
  1125.         break;
  1126.     case MACH_EXC_TLB_LD_MISS:
  1127.     case MACH_EXC_TLB_ST_MISS:
  1128.         if (VmMach_TLBFault(badVaddr) != SUCCESS) {
  1129.         printf("Bad user TLB fault in process %x: pc=%x addr=%x\n",
  1130.             procPtr->processID, pc, badVaddr);
  1131.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1132.                 procPtr->processID, FALSE, badVaddr);
  1133.         }
  1134.         break;
  1135.     case MACH_EXC_ADDR_ERR_LD:
  1136.     case MACH_EXC_ADDR_ERR_ST:
  1137.         printf("Address fault in process %x: pc=%x addr=%x\n",
  1138.             procPtr->processID, pc, badVaddr);
  1139.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1140.                 procPtr->processID, FALSE, badVaddr);
  1141.         break;
  1142.     case MACH_EXC_BUS_ERR_IFETCH:
  1143.         printf("MachExceptionHandler: User bus error on ifetch");
  1144.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1145.                 procPtr->processID, FALSE, badVaddr);
  1146.         break;
  1147.     case MACH_EXC_BUS_ERR_LD_ST:
  1148.         printf("MachExceptionHandler: User bus error on ld or st");
  1149.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1150.                 procPtr->processID, FALSE, badVaddr);
  1151.         break;
  1152.     case MACH_EXC_SYSCALL:
  1153.         if (!MachUNIXSyscallNew()) {
  1154.         printf("MachExceptionHandler: Bad syscall magic for proc %x\n",
  1155.                             procPtr->processID);
  1156.         (void) Sig_Send(SIG_ILL_INST, SIG_BAD_TRAP,
  1157.                 procPtr->processID, FALSE, pc);
  1158.         }
  1159.         break;
  1160.     case MACH_EXC_BREAK: {
  1161.         unsigned inst;
  1162.         /*
  1163.          * Check to see if this is a return from signal handler
  1164.          * break or a normal breakpoint.
  1165.          */
  1166.         if (Vm_CopyIn(sizeof(int), pc, (Address)&inst) != SUCCESS) {
  1167.         panic("MachExceptionHandler: Couldn't fetch break inst.");
  1168.         }
  1169. #if 0
  1170.         printf("Pc = 0x%x, Instruction = 0x%x\n", pc, inst);
  1171.         printf("Cause register = 0x%x\n", causeReg);
  1172. #endif
  1173.         switch ((int)(inst & MACH_BREAK_CODE_FIELD)) {
  1174.         case MACH_BREAKPOINT_VAL:
  1175.             Proc_Lock(procPtr);
  1176.             if (procPtr->genFlags & PROC_DEBUG_ON_EXEC) {
  1177.             procPtr->genFlags &= ~PROC_DEBUG_ON_EXEC;
  1178.             (void) Sig_SendProc(procPtr, SIG_DEBUG, 
  1179.                         SIG_NO_CODE, pc);
  1180.             } else {
  1181.             (void) Sig_SendProc(procPtr, SIG_BREAKPOINT, 
  1182.                         SIG_NO_CODE, pc);
  1183.             }
  1184.             Proc_Unlock(procPtr);
  1185.             break;
  1186.         case MACH_SSTEP_VAL: {
  1187.             ReturnStatus    status;
  1188.  
  1189.             Vm_ChangeCodeProt(procPtr, pc, 4, TRUE);
  1190.             status = Vm_CopyOut(4, (Address)&machCurStatePtr->sstepInst,                    pc);
  1191.             Vm_ChangeCodeProt(procPtr, pc, 4, FALSE);
  1192.             Vm_FlushCode(procPtr, pc, 4);
  1193.             if (status != SUCCESS) {
  1194.             panic("MachUserExceptionHandler: Bad sstep PC\n");
  1195.             }
  1196.             Proc_Lock(procPtr);
  1197.             (void) Sig_SendProc(procPtr, SIG_TRACE_TRAP, SIG_NO_CODE,
  1198.                 pc);
  1199.             Proc_Unlock(procPtr);
  1200.             break;
  1201.         }
  1202.  
  1203.         case MACH_SIG_RET_VAL:
  1204.             ReturnFromSigHandler(procPtr);
  1205.             break;
  1206.         default:
  1207.             printf("Bogus bp-trap\n");
  1208.             (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1209.                     procPtr->processID, FALSE, pc);
  1210.             break;
  1211.         }
  1212.         break;
  1213.     }
  1214.     case MACH_EXC_RES_INST:
  1215.         printf("Reserved instruction in process %x at pc=%x\n",
  1216.             procPtr->processID, pc);
  1217.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1218.                 procPtr->processID, FALSE, pc);
  1219.         break;
  1220.     case MACH_EXC_COP_UNUSABLE:
  1221.         MachSwitchFPState(machFPCurStatePtr, machCurStatePtr);
  1222.         machFPCurStatePtr = machCurStatePtr;
  1223.         break;
  1224.     case MACH_EXC_OVFLOW:
  1225.         printf("Overflow exception in process %x at pc=%x\n",
  1226.             procPtr->processID, pc);
  1227.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_OVERFLOW,
  1228.                 procPtr->processID, FALSE, pc);
  1229.         break;
  1230.     }
  1231.     retVal = MachUserReturn(procPtr);
  1232.  
  1233.     return(retVal);
  1234. }
  1235.  
  1236.  
  1237. /*
  1238.  * ----------------------------------------------------------------------------
  1239.  *
  1240.  * MachKernelExceptionHandler --
  1241.  *
  1242.  *      Handle a kernel exception.
  1243.  *
  1244.  * Results:
  1245.  *      MACH_KERN_ERROR if the debugger should be called after this routine 
  1246.  *    returns, MACH_USER_ERROR if a copy to/from user space caused an 
  1247.  *    unrecoverable bus error, and MACH_OK if everything worked out ok.
  1248.  *
  1249.  * Side effects:
  1250.  *      None.
  1251.  *
  1252.  * ----------------------------------------------------------------------------
  1253.  */
  1254. int
  1255. MachKernelExceptionHandler(statusReg, causeReg, badVaddr, pc)
  1256.     unsigned    statusReg;    /* The status register at the time of the
  1257.                  * exception. */
  1258.     unsigned    causeReg;    /* The cause register - contains the type
  1259.                  * of exception. */
  1260.     Address    badVaddr;    /* The address (if any) that the fault
  1261.                  * occured on. */
  1262.     Address    pc;        /* Program counter where to continue. */
  1263. {
  1264.     register    Proc_ControlBlock    *procPtr;
  1265.     ReturnStatus            status;
  1266.     int                    cause;
  1267.  
  1268.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  1269.     machBadVaddr = badVaddr;
  1270.  
  1271.     /*
  1272.      * Process kernel traps.
  1273.      */
  1274.     procPtr = Proc_GetActualProc();
  1275.     switch (cause) {
  1276.     case MACH_EXC_INT:
  1277.         status = Interrupt(statusReg, causeReg, pc);
  1278.         return(status);
  1279.     case MACH_EXC_TLB_LD_MISS:
  1280.     case MACH_EXC_TLB_ST_MISS:
  1281.     case MACH_EXC_TLB_MOD: {
  1282.         Boolean    copyInProgress = FALSE;
  1283.  
  1284.         if (statusReg & MACH_SR_INT_ENA_PREV) {
  1285.         /*
  1286.          * Enable interrupts.
  1287.          */
  1288.         Mach_EnableIntr();
  1289.         }
  1290.  
  1291.         if (pc >= F_TO_A Vm_CopyIn && pc < F_TO_A VmMachCopyEnd) {
  1292.         copyInProgress = TRUE;
  1293.         } else if (pc >= F_TO_A MachFetchArgs &&
  1294.                    pc <= F_TO_A MachFetchArgsEnd) {
  1295.         copyInProgress = TRUE;
  1296.         } else if (badVaddr < (Address)VMMACH_VIRT_CACHED_START &&
  1297.                (badVaddr >= (Address)VMMACH_PHYS_CACHED_START ||
  1298.             procPtr == (Proc_ControlBlock *)NIL ||
  1299.             procPtr->vmPtr->numMakeAcc == 0)) {
  1300.         if (procPtr != (Proc_ControlBlock *)NIL) {
  1301.             printf("%s: note: procPtr->vmPtr->numMakeAcc = %d\n", 
  1302.                "MachKernelExceptionHandler",
  1303.                procPtr->vmPtr->numMakeAcc);
  1304.         }
  1305.         return(MACH_KERN_ERROR);
  1306.         }
  1307.         if (((causeReg & MACH_CR_EXC_CODE) >> 
  1308.             MACH_CR_EXC_CODE_SHIFT) == MACH_EXC_TLB_MOD) {
  1309.         status = VmMach_TLBModFault(badVaddr);
  1310.         } else {
  1311.         status = VmMach_TLBFault(badVaddr);
  1312.         }
  1313.         if (status != SUCCESS) {
  1314.         if (copyInProgress) {
  1315.             return(MACH_USER_ERROR);
  1316.         } else {
  1317.             printf("badVaddr = 0x%x\n", badVaddr);
  1318.             return(MACH_KERN_ERROR);
  1319.         }
  1320.         } else {
  1321.         return(MACH_OK);
  1322.         }
  1323.     }
  1324.  
  1325.     case MACH_EXC_ADDR_ERR_LD:
  1326.         printf("MachKernelExceptionHandler: %s: addr: %x PC: %x\n",
  1327.             "Address error on load", badVaddr, pc);
  1328.         return(MACH_KERN_ERROR);
  1329.     case MACH_EXC_ADDR_ERR_ST:
  1330.         printf("MachKernelExceptionHandler:  Address error on store\n");
  1331.         return(MACH_KERN_ERROR);
  1332.     case MACH_EXC_BUS_ERR_IFETCH:
  1333.         printf("MachKernelExceptionHandler:  Bus error on ifetch\n");
  1334.         return(MACH_KERN_ERROR);
  1335.     case MACH_EXC_BUS_ERR_LD_ST:
  1336.         if (machInProbe) {
  1337.         return(MACH_OK);
  1338.         }
  1339.         printf("MachKernelExceptionHandler:  Bus error on load or store\n");
  1340.         return(MACH_KERN_ERROR);
  1341.     case MACH_EXC_SYSCALL:
  1342.         printf("MachKernelExceptionHandler:  System call in kernel mode\n");
  1343.         return(MACH_KERN_ERROR);
  1344.     case MACH_EXC_BREAK:
  1345.         return(MACH_KERN_ERROR);
  1346.     case MACH_EXC_RES_INST:
  1347.         printf("MachKernelExceptionHandler:  Reserved instruction\n");
  1348.         return(MACH_KERN_ERROR);
  1349.     case MACH_EXC_COP_UNUSABLE:
  1350.         printf("MachKernelExceptionHandler:  Coprocessor unusable\n");
  1351.         return(MACH_KERN_ERROR);
  1352.     case MACH_EXC_OVFLOW:
  1353.         printf("MachKernelExceptionHandler:  Overflow\n");
  1354.         return(MACH_KERN_ERROR);
  1355.     default:
  1356.         printf("MachKernelExceptionHandler: Unknown exception\n");
  1357.         return(MACH_KERN_ERROR);
  1358.     }
  1359. }
  1360.  
  1361.  
  1362. /*
  1363.  * ----------------------------------------------------------------------------
  1364.  *
  1365.  * Interrupt --
  1366.  *
  1367.  *      Call the proper interrupt handler for the given interrupt.
  1368.  *
  1369.  * Results:
  1370.  *      MACH_KERN_ERROR if the machine should go into the debugger, or MACH_OK
  1371.  *    otherwise.
  1372.  *
  1373.  * Side effects:
  1374.  *      None.
  1375.  *
  1376.  * ----------------------------------------------------------------------------
  1377.  */
  1378. static ReturnStatus
  1379. Interrupt(statusReg, causeReg, pc)
  1380.     unsigned    statusReg;
  1381.     unsigned    causeReg;
  1382.     Address    pc;
  1383. {
  1384.     int        n;
  1385.     unsigned    mask;
  1386.     ReturnStatus status = MACH_OK;
  1387.  
  1388.     mask = (causeReg & statusReg & MACH_CR_INT_PENDING) >> 
  1389.                         MACH_CR_HARD_INT_SHIFT;
  1390.     mach_KernelMode = !(statusReg & MACH_SR_KU_PREV);
  1391.     mach_AtInterruptLevel = 1;
  1392.  
  1393.     /*
  1394.      * If there is a memory interrupt pending, and we have all other
  1395.      * interrupts off, then only handle that interrupt.
  1396.      */
  1397.  
  1398.     if (mach_NumDisableIntrsPtr[Mach_GetProcessorNumber()] > 0) {
  1399.     if (mask & (MACH_INT_MASK_3 >> MACH_CR_HARD_INT_SHIFT)) {
  1400.         status = machInterruptRoutines[3](statusReg, causeReg, pc, 
  1401.             machInterruptArgs[3]); 
  1402.         goto exit;
  1403.     } else {
  1404.         panic("Interrupt while at interrupt level, (0x%x) pc 0x%x.\n", 
  1405.         mask, pc);
  1406.     }
  1407.     }
  1408.     n = 0;
  1409.     while (mask != 0) {
  1410.     if (mask & 1) {
  1411.         (void) machInterruptRoutines[n](statusReg, causeReg, pc, 
  1412.         machInterruptArgs[n]); 
  1413.     }
  1414.     mask >>= 1;
  1415.     n++;
  1416.     }
  1417. exit:
  1418.     mach_AtInterruptLevel = 0;
  1419.     return(status);
  1420. }
  1421.  
  1422.  
  1423. /*
  1424.  * ----------------------------------------------------------------------------
  1425.  *
  1426.  * MachUserReturn --
  1427.  *
  1428.  *      Take the proper action to return from a user exception.
  1429.  *
  1430.  * Results:
  1431.  *      None.
  1432.  *
  1433.  * Side effects:
  1434.  *      Interrupts disabled.
  1435.  *
  1436.  * ----------------------------------------------------------------------------
  1437.  */
  1438. Boolean
  1439. MachUserReturn(procPtr)
  1440.     register    Proc_ControlBlock    *procPtr;
  1441. {
  1442.     SignalStack    sigStack;
  1443.     Address    pc;
  1444.     int        restarted = 0;
  1445.     Address    savePC;
  1446.  
  1447.  
  1448.     if (procPtr->Prof_Scale >= 2 && procPtr->Prof_PC != 0) {
  1449.     Prof_RecordPC(procPtr);
  1450.     }
  1451.  
  1452.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1453.         procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1454.     printf("UnixProgress = %d entering MachUserReturn\n",
  1455.         procPtr->unixProgress);
  1456.     }
  1457.  
  1458.     /* 
  1459.      * Take a context switch if one is pending for this process.
  1460.      */
  1461.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1462.     Sched_LockAndSwitch();
  1463.     }
  1464.  
  1465.     while (TRUE) {
  1466.     /*
  1467.      * See if we are supposed to single-step this process.  If so
  1468.      * put a break in the proper place.  Don't worry if we miss a signal
  1469.      * because we will be back in real soon anyway (after one instruction).
  1470.      */
  1471.     if (procPtr->genFlags & PROC_SINGLE_STEP_FLAG) {
  1472.         Address        breakPC;
  1473.         unsigned        breakInst;
  1474.         ReturnStatus    status;
  1475.         int            accLen;
  1476.         Address        newAddr;
  1477.  
  1478.         if (machFPCurStatePtr == machCurStatePtr) {
  1479.         MachGetCurFPState(machCurStatePtr);
  1480.         }
  1481.         Vm_MakeAccessible(VM_READONLY_ACCESS, sizeof(Address),
  1482.                   machCurStatePtr->userState.regState.pc, 
  1483.                   &accLen, &newAddr);
  1484.         if (accLen != sizeof(Address)) {
  1485.         printf("MachUserReturn: Can't fetch user's trap PC\n");
  1486.         break;
  1487.         }
  1488.         breakPC = (Address)
  1489.             MachEmulateBranch(machCurStatePtr->userState.regState.regs,
  1490.                       machCurStatePtr->userState.regState.pc,
  1491.                  machCurStatePtr->userState.regState.fpStatusReg,
  1492.                          TRUE);
  1493.         Vm_MakeUnaccessible(newAddr, sizeof(Address));
  1494.         if (Vm_CopyIn(4, breakPC,
  1495.               (Address)&machCurStatePtr->sstepInst) != SUCCESS) {
  1496.         printf("Bad single-step address\n");
  1497.         } else {
  1498.         breakInst = MACH_SSTEP_VAL | 0xd;
  1499.         Vm_ChangeCodeProt(procPtr, breakPC, 4, TRUE);
  1500.         status = Vm_CopyOut(4, (Address)&breakInst, breakPC);
  1501.         Vm_ChangeCodeProt(procPtr, breakPC, 4, FALSE);
  1502.         Vm_FlushCode(procPtr, breakPC, 4);
  1503.         if (status != SUCCESS) {
  1504.             printf("Bad single-step address\n");
  1505.         }
  1506.         }
  1507.         procPtr->genFlags &= ~PROC_SINGLE_STEP_FLAG;
  1508.         Mach_DisableIntr();
  1509.         break;
  1510.     } else {
  1511.         if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1512.             procPtr->unixProgress > 0) {
  1513.         /*
  1514.          * If we received a normal signal, we want to restart
  1515.          * the system call when we leave.
  1516.          * If we received a migrate signal, we will get here on
  1517.          * the new machine.
  1518.          */
  1519.  
  1520.         /*
  1521.          * Mangle the PC so we restart the trap after we leave
  1522.          * the kernel.
  1523.          */
  1524.         restarted = 1;
  1525.         if (debugProcStubs) {
  1526.             printf("Restarting system call with progress %d\n",
  1527.                 procPtr->unixProgress);
  1528.         }
  1529.         }
  1530.         /*
  1531.          * Disable interrupts.  Note that we don't use the DISABLE_INTR 
  1532.          * macro because it increments the nesting depth of interrupts
  1533.          * which we don't want because there is an implicit enable
  1534.          * interrupts on rte.
  1535.          */
  1536.         Mach_DisableIntr();
  1537.         if (!Sig_Pending(procPtr)) {
  1538.         break;
  1539.         }
  1540.         Mach_EnableIntr();
  1541.         savePC = machCurStatePtr->userState.regState.pc;
  1542.         if (restarted) {
  1543.         /*
  1544.          * We have to move the PC now so the migrated process
  1545.          * will start in the right place.
  1546.          * If we don't migrate, we put the PC back after the
  1547.          * Sig_Handle.
  1548.          */
  1549.         machCurStatePtr->userState.regState.pc -= 4;
  1550.         }
  1551.         sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1552.         if (Sig_Handle(procPtr, &sigStack.sigStack, &pc)) {
  1553.         SetupSigHandler(procPtr, &sigStack, pc);
  1554.         Mach_DisableIntr();
  1555.         break;
  1556.         } else {
  1557.         if (procPtr->unixProgress == PROC_PROGRESS_MIG_RESTART ||
  1558.             procPtr->unixProgress == PROC_PROGRESS_RESTART) {
  1559.             restarted = 1;
  1560.             if (debugProcStubs) {
  1561.             printf("No signal action, so we restarted call\n");
  1562.             }
  1563.         } else if (restarted && debugProcStubs) {
  1564.             printf("No signal, yet we restarted system call!\n");
  1565.         }
  1566.         }
  1567.         /*
  1568.          * Restore PC if we didn't migrate.
  1569.          */
  1570.         machCurStatePtr->userState.regState.pc = savePC;
  1571.     }
  1572.     }
  1573.     
  1574.     /*
  1575.      * It is possible for Sig_Handle to mask the migration signal
  1576.      * if a process is not in a state where it can be migrated.
  1577.      * As soon as we return to user mode, though, we will allow migration.
  1578.      */
  1579.     Sig_AllowMigration(procPtr);
  1580.  
  1581.     if (restarted) {
  1582.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1583.     if (debugProcStubs) {
  1584.         printf("Moving the PC to restart the system call\n");
  1585.         printf("Our PC = %x\n",
  1586.             machCurStatePtr->userState.regState.pc);
  1587.     }
  1588.     machCurStatePtr->userState.regState.pc -= 4;
  1589.     if (debugProcStubs) {
  1590.         printf("Now our PC = %x\n",
  1591.             machCurStatePtr->userState.regState.pc);
  1592.         printf("V0 was %d and our call was %d\n", 
  1593.             machCurStatePtr->userState.regState.regs[V0],
  1594.             machCurStatePtr->userState.unixRetVal);
  1595.         printf("Our incoming a0-a3 were %x %x %x %x\n", 
  1596.             machCurStatePtr->userState.regState.regs[A0],
  1597.             machCurStatePtr->userState.regState.regs[A1],
  1598.             machCurStatePtr->userState.regState.regs[A2],
  1599.             machCurStatePtr->userState.regState.regs[A3]);
  1600.     }
  1601.     /*
  1602.      * Our V0 and A3 will have been clobbered by the system call, so
  1603.      * we have to restore them.
  1604.      */
  1605.     machCurStatePtr->userState.regState.regs[V0] =
  1606.         machCurStatePtr->userState.savedV0;
  1607.     machCurStatePtr->userState.regState.regs[A3] =
  1608.         machCurStatePtr->userState.savedA3;
  1609.     }
  1610.  
  1611.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1612.         procPtr->unixProgress != PROC_PROGRESS_UNIX) {
  1613.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1614.     if (debugProcStubs) {
  1615.         printf("UnixProgress = %d leaving MachUserReturn!\n",
  1616.             procPtr->unixProgress);
  1617.     }
  1618.     }
  1619.  
  1620.     return(machFPCurStatePtr == machCurStatePtr);
  1621. }
  1622.  
  1623. /*
  1624.  * ----------------------------------------------------------------------------
  1625.  *
  1626.  * Routines to set up and return from signal handlers.
  1627.  *
  1628.  * In order to call a handler four things must be done:
  1629.  *
  1630.  *    1) The current state of the process must be saved so that when
  1631.  *       the handler returns a normal return to user space can occur.
  1632.  *    2) The user stack must be set up so that the signal number and the
  1633.  *       the signal code are passed to the handler.
  1634.  *    3) Things must be set up so that when the handler returns it returns
  1635.  *       back into the kernel so that state can be cleaned up.
  1636.  *    4) The trap stack that was created when the kernel was entered and is
  1637.  *       used to return a process to user space must be modified so that
  1638.  *       the signal handler is called instead of executing the
  1639.  *       normal return.
  1640.  *
  1641.  * The last one is done by simply changing the program counter where the
  1642.  * user process will execute on return to be the address of the signal
  1643.  * handler and the user stack pointer to point to the proper place on
  1644.  * the user stack.  The first three of these are accomplished by 
  1645.  * setting up the user's registers properly.  The return address register is the
  1646.  * return address where the handler will start executing upon return.  But 
  1647.  * this is just the address of a trap instruction that is stored on the stack
  1648.  * below.  Thus when a handler returns it will execute a trap instruction 
  1649.  * and drop back into the kernel. 
  1650.  */
  1651.  
  1652.  
  1653. /*
  1654.  * ----------------------------------------------------------------------------
  1655.  *
  1656.  * SetupSigHandler --
  1657.  *
  1658.  *      Save machine state on the users stack and set up the exception stack
  1659.  *    so that the user will call the signal handler on return. In order to
  1660.  * Results:
  1661.  *      None.
  1662.  *
  1663.  * Side effects:
  1664.  *      Signal stack set up and saved.
  1665.  *
  1666.  * ----------------------------------------------------------------------------
  1667.  */
  1668. static void
  1669. SetupSigHandler(procPtr, sigStackPtr, pc)
  1670.     register    Proc_ControlBlock    *procPtr;
  1671.     register    SignalStack        *sigStackPtr;
  1672.     Address                pc;
  1673. {
  1674.     Mach_UserState    *userStatePtr;
  1675.     unsigned        usp;
  1676.  
  1677.     userStatePtr = &procPtr->machStatePtr->userState;
  1678.     usp = userStatePtr->regState.regs[SP] - sizeof(Sig_Context) - 
  1679.       MACH_STAND_FRAME_SIZE;
  1680.  
  1681.     sigStackPtr->sigContext.machContext.break1Inst = 0x1000d;
  1682.     /*
  1683.      * Copy the user state onto the signal stack.
  1684.      */
  1685.     bcopy((Address)userStatePtr,
  1686.           (Address)&(sigStackPtr->sigContext.machContext.userState),
  1687.           sizeof(Mach_UserState));
  1688.     /*
  1689.      * Copy over the floating point state.
  1690.      */
  1691.     if (machFPCurStatePtr == machCurStatePtr) {
  1692.     MachGetCurFPState(machCurStatePtr);
  1693.     }
  1694.     bcopy((Address)procPtr->machStatePtr->userState.regState.fpRegs,
  1695.       (Address)sigStackPtr->sigContext.machContext.fpRegs,
  1696.       MACH_NUM_FPRS * sizeof(int));
  1697.     sigStackPtr->sigContext.machContext.fpStatusReg =
  1698.             procPtr->machStatePtr->userState.regState.fpStatusReg;
  1699.     /*
  1700.      * Copy the stack out to user space.
  1701.      */
  1702.     if (Vm_CopyOut(sizeof(Sig_Context), (Address)&sigStackPtr->sigContext,
  1703.             (Address)(usp + MACH_STAND_FRAME_SIZE)) != SUCCESS) {
  1704.         printf("Warning: HandleSig: No room on stack for signal, PID=%x.\n",
  1705.                   procPtr->processID);
  1706.         Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1707.     }
  1708.     /*
  1709.      * Now set up the registers correctly.
  1710.      */
  1711.     userStatePtr->regState.regs[SP] = usp;
  1712.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1713.     int unixSignal;
  1714.     if (Compat_SpriteSignalToUnix(sigStackPtr->sigStack.sigNum,
  1715.         &unixSignal) != SUCCESS) {
  1716.         printf("Signal %d invalid in SetupSigHandler\n",
  1717.             sigStackPtr->sigStack.sigNum);
  1718.     } else {
  1719.         userStatePtr->regState.regs[A0] = unixSignal;
  1720.     }
  1721.     } else {
  1722.     userStatePtr->regState.regs[A0] = sigStackPtr->sigStack.sigNum;
  1723.     }
  1724.     userStatePtr->regState.regs[A1] = sigStackPtr->sigStack.sigCode;
  1725.     userStatePtr->regState.regs[A2] = usp + MACH_STAND_FRAME_SIZE;
  1726.     userStatePtr->regState.regs[A3] = sigStackPtr->sigStack.sigAddr;
  1727.     userStatePtr->regState.pc = pc;
  1728.     userStatePtr->regState.regs[RA] = usp + MACH_STAND_FRAME_SIZE + 
  1729.         (unsigned)&((Sig_Context *)0)->machContext.break1Inst;
  1730. }
  1731.  
  1732.  
  1733. /*
  1734.  * ----------------------------------------------------------------------------
  1735.  *
  1736.  * ReturnFromSigHandler --
  1737.  *
  1738.  *      Process a return from a signal handler.
  1739.  *    
  1740.  * Results:
  1741.  *      None.
  1742.  *
  1743.  * Side effects:
  1744.  *      Signal stack struct and size filled in the machine struct for the
  1745.  *    given process.
  1746.  *
  1747.  * ----------------------------------------------------------------------------
  1748.  */
  1749. static void
  1750. ReturnFromSigHandler(procPtr)
  1751.     register    Proc_ControlBlock    *procPtr;
  1752. {
  1753.     register    Mach_State    *statePtr;
  1754.     SignalStack            sigStack;
  1755.  
  1756.     statePtr = procPtr->machStatePtr;
  1757.     /*
  1758.      * Copy the signal stack in.
  1759.      */
  1760.     if (Vm_CopyIn(sizeof(Sig_Context),
  1761.           (Address)(statePtr->userState.regState.regs[SP] + 
  1762.                 MACH_STAND_FRAME_SIZE),
  1763.           (Address) &sigStack.sigContext) != SUCCESS) {
  1764.     printf("%s Mach_Code: Stack too small to extract trap info, PID=%x.\n",
  1765.         "Warning:", procPtr->processID);
  1766.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1767.     }
  1768.     sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1769.     /*
  1770.      * Take the proper action on return from a signal.
  1771.      */
  1772.     Sig_Return(procPtr, &sigStack.sigStack);
  1773.     /*
  1774.      * Restore user state.
  1775.      */
  1776.     bcopy((Address)&sigStack.sigContext.machContext.userState,
  1777.           (Address)&statePtr->userState, sizeof(statePtr->userState));
  1778.     /*
  1779.      * Copy in the floating point state.
  1780.      */
  1781.     bcopy((Address)sigStack.sigContext.machContext.fpRegs,
  1782.       (Address)statePtr->userState.regState.fpRegs,
  1783.       MACH_NUM_FPRS * sizeof(int));
  1784.     statePtr->userState.regState.fpStatusReg = 
  1785.     sigStack.sigContext.machContext.fpStatusReg & ~MACH_FPC_EXCEPTION_BITS;
  1786.     if (machFPCurStatePtr == machCurStatePtr) {
  1787.     machFPCurStatePtr = (Mach_State *)NIL;
  1788.     }
  1789. }
  1790.  
  1791.  
  1792. /*
  1793.  * ----------------------------------------------------------------------------
  1794.  *
  1795.  * Mach_ProcessorState --
  1796.  *
  1797.  *    Determines what state the processor is in.
  1798.  *
  1799.  * Results:
  1800.  *    MACH_USER    if was at user level
  1801.  *    MACH_KERNEL    if was at kernel level
  1802.  *
  1803.  * Side effects:
  1804.  *    None.
  1805.  *
  1806.  * ----------------------------------------------------------------------------
  1807.  */
  1808. /*ARGSUSED*/
  1809. Mach_ProcessorStates 
  1810. Mach_ProcessorState(processor)
  1811.     int processor;    /* processor number for which info is requested */
  1812. {
  1813.     if (mach_KernelMode) {
  1814.     return(MACH_KERNEL);
  1815.     } else {
  1816.     return(MACH_USER);
  1817.     }
  1818. }
  1819.  
  1820.  
  1821. /*
  1822.  * ----------------------------------------------------------------------------
  1823.  *
  1824.  * Mach_GetMachineArch --
  1825.  *
  1826.  *    Return the machine architecture.
  1827.  *
  1828.  * Results:
  1829.  *    The machine architecture.
  1830.  *
  1831.  * Side effects:
  1832.  *    None.
  1833.  *
  1834.  * ----------------------------------------------------------------------------
  1835.  */
  1836. int
  1837. Mach_GetMachineArch()
  1838. {
  1839.     return SYS_DS5000;
  1840. }
  1841.  
  1842.  
  1843. /*
  1844.  * ----------------------------------------------------------------------------
  1845.  *
  1846.  * Mach_GetMachineType --
  1847.  *
  1848.  *    Return the machine type.
  1849.  *
  1850.  * Results:
  1851.  *    0.
  1852.  *
  1853.  * Side effects:
  1854.  *    None.
  1855.  *
  1856.  * ----------------------------------------------------------------------------
  1857.  */
  1858. int
  1859. Mach_GetMachineType()
  1860. {
  1861.     return 0;
  1862. }
  1863.  
  1864.  
  1865. /*
  1866.  * ----------------------------------------------------------------------------
  1867.  *
  1868.  *  Mach_CheckSpecialHandling--
  1869.  *
  1870.  *    Forces a processor to check the special handling flag of a process.
  1871.  *    This should only be called on a multiprocessor.
  1872.  *
  1873.  * Results:
  1874.  *    None.
  1875.  *
  1876.  * Side effects:
  1877.  *    None.
  1878.  *
  1879.  * ----------------------------------------------------------------------------
  1880.  */
  1881. void
  1882. Mach_CheckSpecialHandling(pnum)
  1883.     int        pnum;        /* Processor number. */
  1884. {
  1885.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1886. }
  1887.  
  1888.  
  1889. /*
  1890.  *----------------------------------------------------------------------
  1891.  *
  1892.  * Mach_GetNumProcessors() --
  1893.  *
  1894.  *    Return the number of processors in the system.  NOTE: This should
  1895.  *    really be in a machine-independent area of the mach module.  Note
  1896.  *    further: if this is used only as a system call, it should return
  1897.  *    a ReturnStatus!
  1898.  *
  1899.  * Results:
  1900.  *    The number of processors is returned.  
  1901.  *
  1902.  * Side effects:
  1903.  *    None
  1904.  *
  1905.  *----------------------------------------------------------------------
  1906.  */
  1907.  
  1908. int
  1909. Mach_GetNumProcessors()
  1910. {
  1911.     return (mach_NumProcessors);
  1912. }
  1913.  
  1914.  
  1915. /*
  1916.  *----------------------------------------------------------------------
  1917.  *
  1918.  * Mach_GetBootArgs --
  1919.  *
  1920.  *    Returns the arguments out of the boot parameter structure. 
  1921.  *
  1922.  * Results:
  1923.  *    Number of elements returned in argv.
  1924.  *
  1925.  * Side effects:
  1926.  *    None.
  1927.  *
  1928.  *----------------------------------------------------------------------
  1929.  */
  1930. /*ARGSUSED*/
  1931. int
  1932. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  1933.     int    argc;            /* Number of elements in argv */
  1934.     int    bufferSize;        /* Size of buffer */
  1935.     char    **argv;            /* Ptr to array of arg pointers */
  1936.     char    *buffer;        /* Storage for arguments */
  1937. {
  1938.     int        i;
  1939.     int        offset;
  1940.  
  1941.     bcopy(machMonBootParam.strings, buffer, 
  1942.       (bufferSize < 256) ? bufferSize : 256);
  1943.     offset = (int) machMonBootParam.strings - (int) buffer;
  1944.     for(i = 0; i < argc; i++) {
  1945.     if (machMonBootParam.argPtr[i] == (char *)NULL) {
  1946.         break;
  1947.     }
  1948.     argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  1949.     }
  1950.     return i;
  1951. }
  1952.  
  1953. /*
  1954.  *----------------------------------------------------------------------
  1955.  *
  1956.  * MachMemInterrupt --
  1957.  *
  1958.  *    Handle an interrupt from the memory controller.
  1959.  *
  1960.  * Results:
  1961.  *    None.
  1962.  *
  1963.  * Side effects:
  1964.  *    None.
  1965.  *
  1966.  *----------------------------------------------------------------------
  1967.  */
  1968. /*ARGSUSED*/
  1969. static ReturnStatus
  1970. MachMemInterrupt(statusReg, causeReg, pc, data)
  1971.     unsigned    statusReg;        /* Status register. */
  1972.     unsigned    causeReg;        /* Cause register. */
  1973.     Address    pc;            /* PC. */
  1974.     ClientData    data;            /* Callback data. */
  1975.  
  1976. {
  1977.     volatile unsigned int *erradrPtr = 
  1978.         (volatile unsigned int *) MACH_ERRADR_ADDR;
  1979.     unsigned int erradr;
  1980.     volatile unsigned int *chksynPtr = 
  1981.         (volatile unsigned int *) MACH_CHKSYN_ADDR;
  1982.     unsigned int chksyn;
  1983.     unsigned int address;
  1984.     int        column;
  1985.     ReturnStatus    status = MACH_OK;
  1986.  
  1987.     erradr = *erradrPtr;
  1988.     if (!(erradr & MACH_ERRADR_VALID)) {
  1989.     printf("Received memory interrupt but ERRADR not valid.\n");
  1990.     return status;
  1991.     }
  1992.     address = erradr & MACH_ERRADR_ADDRESS;
  1993.     switch((int) (erradr & 
  1994.     (MACH_ERRADR_CPU | MACH_ERRADR_WRITE | MACH_ERRADR_ECCERR))){
  1995.     case 0: {
  1996.         /*
  1997.          * For IO space addresses the 27 bits in the ERRADR must be
  1998.          * shifted by 2, then the top bits set.  This isn't documented
  1999.          * anywhere.
  2000.          */
  2001.         address = MACH_IO_SLOT_BASE | (address << 2);
  2002.         panic("DMA read overrun at address 0x%x\n", address);
  2003.         break;
  2004.     } 
  2005.     case (MACH_ERRADR_ECCERR) :  {
  2006.         /*
  2007.          * Compensate for the address pipeline. 
  2008.          * See page 26 of the functional spec.
  2009.          */
  2010.         column = (int) (address & 0xfff); 
  2011.         column -= 5;
  2012.         address = (address & ~0xfff) | (unsigned int) column;
  2013.         printf("ECC read error during DMA at address 0x%x\n", address);
  2014.         break;
  2015.     }
  2016.     case (MACH_ERRADR_WRITE) : {
  2017.         address = MACH_IO_SLOT_BASE | (address << 2);
  2018.         panic("DMA write overrun at address 0x%x, pc = 0x%x\n", 
  2019.         address, pc);
  2020.         break;
  2021.     } 
  2022.     case (MACH_ERRADR_WRITE | MACH_ERRADR_ECCERR) : {
  2023.         printf("Holy bogus hardware, Batman!\n");
  2024.         printf("We got an illegal value in the ERRADR status register.\n");
  2025.         break;
  2026.     }
  2027.     case (MACH_ERRADR_CPU) : {
  2028.         address = MACH_IO_SLOT_BASE | (address << 2);
  2029.         if (machInProbe) {
  2030.         status = MACH_USER_ERROR;
  2031.         machInProbe = FALSE;
  2032.         break;
  2033.         }
  2034.         panic(
  2035.     "Timeout during CPU read of IO address 0x%x, pc = 0x%x\n", 
  2036.     address, pc);
  2037.         Mach_SendSignal(MACH_SIGILL);
  2038.         break;
  2039.     }
  2040.     case (MACH_ERRADR_CPU | MACH_ERRADR_ECCERR) : {
  2041.         /*
  2042.          * Compensate for the address pipeline. 
  2043.          * See page 26 of the functional spec.
  2044.          */
  2045.         column = (int) (address & 0xfff); 
  2046.         column -= 5;
  2047.         address = (address & ~0xfff) | (unsigned int) column;
  2048.         printf("ECC read error during CPU access of address 0x%x\n", 
  2049.         address);
  2050.         break;
  2051.     }
  2052.     case (MACH_ERRADR_CPU | MACH_ERRADR_WRITE) : {
  2053.         address = MACH_IO_SLOT_BASE | (address << 2);
  2054.         if (machInProbe) {
  2055.         status = MACH_USER_ERROR;
  2056.         machInProbe = FALSE;
  2057.         break;
  2058.         }
  2059.         panic(
  2060.     "Timeout during CPU write of IO address 0x%x\n, pc = 0x%x\n", 
  2061.     address, pc);
  2062.         break;
  2063.     }
  2064.     case (MACH_ERRADR_CPU | MACH_ERRADR_WRITE | MACH_ERRADR_ECCERR) : {
  2065.         printf("ECC partial memory write error by CPU at address 0x%x\n",
  2066.         address);
  2067.         break;
  2068.     }
  2069.     }
  2070.     if (erradr & MACH_ERRADR_ECCERR) {
  2071.     chksyn = *chksynPtr;
  2072.     if (address & 0x1) {
  2073.         printf("ECC error was in the high bank.\n");
  2074.         printf("%s bit error\n", (chksyn & MACH_CHKSYN_SNGHI) ? 
  2075.         "single" : "multiple");
  2076.         printf("Syndrome bits = 0x%x\n", chksyn & MACH_CHKSYN_SYNHI);
  2077.         if (chksyn & MACH_CHKSYN_VLDHI) {
  2078.         printf("Check bits = 0x%x\n", chksyn & MACH_CHKSYN_CHKHI);
  2079.         } else {
  2080.         printf("Check bits not valid.\n");
  2081.         }
  2082.     } else {
  2083.         printf("ECC error was in the low bank.\n");
  2084.         printf("%s bit error\n", (chksyn & MACH_CHKSYN_SNGLO) ? 
  2085.         "single" : "multiple");
  2086.         printf("Syndrome bits = 0x%x\n", chksyn & MACH_CHKSYN_SYNLO);
  2087.         if (chksyn & MACH_CHKSYN_VLDLO) {
  2088.         printf("Check bits = 0x%x\n", chksyn & MACH_CHKSYN_CHKLO);
  2089.         } else {
  2090.         printf("Check bits not valid.\n");
  2091.         }
  2092.     }
  2093.     }
  2094.     /*
  2095.      * Clear the ERRADR and CHKSYN registers.
  2096.      */
  2097.     *erradrPtr = 0;
  2098.     return status;
  2099. }
  2100.  
  2101. /*
  2102.  *----------------------------------------------------------------------
  2103.  *
  2104.  * MachIOInterrupt --
  2105.  *
  2106.  *    Handle an interrupt from one of the IO slots.
  2107.  *
  2108.  * Results:
  2109.  *    None.
  2110.  *
  2111.  * Side effects:
  2112.  *    None.
  2113.  *
  2114.  *----------------------------------------------------------------------
  2115.  */
  2116. /*ARGSUSED*/
  2117. static ReturnStatus
  2118. MachIOInterrupt(statusReg, causeReg, pc, data)
  2119.     unsigned int    statusReg;    /* Status register. */
  2120.     unsigned int    causeReg;    /* Cause register. */
  2121.     Address        pc;        /* PC. */
  2122.     ClientData        data;        /* Not used. */
  2123. {
  2124.     volatile unsigned int     *csrPtr = (unsigned int *) MACH_CSR_ADDR;
  2125.     unsigned int         csr;
  2126.     int                slot;
  2127.     unsigned int        ioint;
  2128.  
  2129.     csr = *csrPtr;
  2130.     ioint = csr & MACH_CSR_IOINT;
  2131.     if (ioint == 0) {
  2132.     panic("No interrupt pending on an IO slot.\n");
  2133.     }
  2134.     for (slot = 0; ioint != 0; slot++, ioint >>= 1) {
  2135.     if (ioint & 1) {
  2136.         if (machIOInterruptRoutines[slot] != (void (*)()) NIL) {
  2137.         machIOInterruptRoutines[slot](machIOInterruptArgs[slot]);
  2138.         }
  2139.     }
  2140.     }
  2141.     return MACH_OK;
  2142. }
  2143.  
  2144.  
  2145. /*
  2146.  *----------------------------------------------------------------------
  2147.  *
  2148.  * Mach_FlushCode --
  2149.  *
  2150.  *    Flush the kernel code from the icache at the given address.
  2151.  *
  2152.  * Results:
  2153.  *    None.
  2154.  *
  2155.  * Side effects:
  2156.  *    None.
  2157.  *
  2158.  *----------------------------------------------------------------------
  2159.  */
  2160. void
  2161. Mach_FlushCode(addr, len) 
  2162.     Address    addr;
  2163.     unsigned    len;
  2164. {
  2165.     unsigned cacheAddr;
  2166.  
  2167.     cacheAddr = VMMACH_PHYS_UNCACHED_START - machInstCacheSize +  
  2168.         ((unsigned)addr & (machInstCacheSize - 1));
  2169. #ifdef notdef
  2170.     printf("len=%d addr=%x cacheAddr=%x\n", len, addr, cacheAddr);
  2171. #endif
  2172.     MachCleanICache(cacheAddr, len);
  2173. }
  2174.  
  2175.  
  2176. /*
  2177.  *----------------------------------------------------------------------
  2178.  *
  2179.  * Mach_SendSignal
  2180.  *
  2181.  *    Send either an illegal instruction or a floating point exception
  2182.  *    to the current process.
  2183.  *
  2184.  * Results:
  2185.  *    None.
  2186.  *
  2187.  * Side effects:
  2188.  *    None.
  2189.  *
  2190.  *----------------------------------------------------------------------
  2191.  */
  2192. void
  2193. Mach_SendSignal(sigType)
  2194.     int    sigType;
  2195. {
  2196.     Proc_ControlBlock    *procPtr;
  2197.  
  2198.     procPtr = Proc_GetActualProc();
  2199.  
  2200.     printf("Mach_SendSignal: Sending signal\n");
  2201.  
  2202.     switch ((int)sigType) {
  2203.     case MACH_SIGFPE:
  2204.         (void) Sig_Send(SIG_ILL_INST, SIG_FP_EXCEPTION,
  2205.                 procPtr->processID, FALSE, (Address)0);
  2206.         break;
  2207.     case MACH_SIGILL:
  2208.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  2209.                 procPtr->processID, FALSE, (Address)0);
  2210.         break;
  2211.     default:
  2212.         panic("Mach_SendSignal: Bad signal type\n");
  2213.         break;
  2214.     }
  2215. }
  2216.  
  2217.  
  2218. /*
  2219.  *----------------------------------------------------------------------
  2220.  *
  2221.  * Mach_ArgParseCode --
  2222.  *
  2223.  *    Parse an argument string.
  2224.  *      Note: this replaces the DECstation argvize prom call that has
  2225.  *    been disabled on the ds5000 for no good reason.
  2226.  *
  2227.  * Results:
  2228.  *    Returns argc,argv in table.
  2229.  *
  2230.  * Side effects:
  2231.  *    None.
  2232.  *
  2233.  *----------------------------------------------------------------------
  2234.  */
  2235. Mach_ArgParseCode(string,table)
  2236. char *string;
  2237. MachStringTable *table;
  2238. {
  2239.     char *ptr1, *ptr2,*end2;
  2240.     table->num = 0;
  2241.     ptr1 = string;
  2242.     ptr2 = table->strings;
  2243.     end2 = table->strings+256;
  2244.     table->argPtr[0] = ptr2;
  2245.     for (;*ptr1 != 0 && ptr2<end2; ptr2++) {
  2246.     if (*ptr1 == ' ') {
  2247.         while(*ptr1 == ' ') {
  2248.         ptr1++;
  2249.         }
  2250.         if (*ptr1 == '\0') {
  2251.         break;
  2252.         }
  2253.         *ptr2 = '\0';
  2254.         table->num++;
  2255.         if (table->num>=16) {
  2256.         break;
  2257.         }
  2258.         table->argPtr[table->num] = ptr2+1;
  2259.     } else {
  2260.         *ptr2 = *ptr1;
  2261.         ptr1++;
  2262.     }
  2263.     }
  2264. }
  2265.  
  2266. /*
  2267.  *----------------------------------------------------------------------
  2268.  *
  2269.  * Mach_GetEtherAddress --
  2270.  *
  2271.  *    Returns the ethernet address of the first ethernet interface.
  2272.  *
  2273.  * Results:
  2274.  *    None.
  2275.  *
  2276.  * Side effects:
  2277.  *    *etherAddrPtr gets the ethernet address.
  2278.  *
  2279.  *----------------------------------------------------------------------
  2280.  */
  2281.  
  2282. void
  2283. Mach_GetEtherAddress(etherAddrPtr)
  2284.     Net_EtherAddress    *etherAddrPtr;    /* Place to put ethernet address. */
  2285. {
  2286.     Net_Interface    *interPtr;
  2287.  
  2288.     interPtr = Net_GetInterface(NET_NETWORK_ETHER, 0);
  2289.     if (interPtr != (Net_Interface *) NIL) {
  2290.     Net_GetAddress(&interPtr->netAddress[NET_PROTO_RAW], etherAddrPtr);
  2291.     }
  2292. }
  2293.  
  2294. #define READ_ROM(from, to, count) {             \
  2295.     int    _i;                        \
  2296.     for(_i = 0; _i < (count); _i++) {            \
  2297.     status = Mach_Probe(1, (from), &((to)[_i]));    \
  2298.     if (status != SUCCESS) {            \
  2299.         return status;                \
  2300.     }                        \
  2301.     (from) += 4;                    \
  2302.     }                            \
  2303. }
  2304.  
  2305. /*
  2306.  *----------------------------------------------------------------------
  2307.  *
  2308.  * Mach_GetSlotInfo --
  2309.  *
  2310.  *    Read the standard information from the ROM in a TURBOchannel
  2311.  *     slot.  Any trailing spaces are converted to null characters.
  2312.  *    See page 13 of the TURBOchannel Hardware Specification for
  2313.  *     details on the format of the ROM.
  2314.  *
  2315.  * Results:
  2316.  *    SUCCESS if the ROM was read ok, FAILURE otherwise
  2317.  *
  2318.  * Side effects:
  2319.  *    None.
  2320.  *
  2321.  *----------------------------------------------------------------------
  2322.  */
  2323. ReturnStatus
  2324. Mach_GetSlotInfo(romAddr, infoPtr)
  2325.     char        *romAddr;    /* ROM address. */
  2326.     Mach_SlotInfo    *infoPtr;    /* Slot information. */
  2327. {
  2328.     ReturnStatus    status = SUCCESS;
  2329.     unsigned char    value;
  2330.     int            i;
  2331.  
  2332.  
  2333.     /*
  2334.      * Move to the start of the standard TURBOchannel rom info. 
  2335.      */
  2336.     romAddr += MACH_IO_ROM_OFFSET + 0x10;
  2337.     /*
  2338.      * Check the test pattern.
  2339.      */
  2340.     READ_ROM(romAddr, &value, 1);
  2341.     if (value != 0x55) {
  2342.     return FAILURE;
  2343.     }
  2344.     READ_ROM(romAddr, &value, 1);
  2345.     if (value != 0x00) {
  2346.     return FAILURE;
  2347.     }
  2348.     READ_ROM(romAddr, &value, 1);
  2349.     if (value != 0xaa) {
  2350.     return FAILURE;
  2351.     }
  2352.     READ_ROM(romAddr, &value, 1);
  2353.     if (value != 0xff) {
  2354.     return FAILURE;
  2355.     }
  2356.     /*
  2357.      * Everything looks cool so read out the info.
  2358.      */
  2359.     READ_ROM(romAddr, infoPtr->revision, 8);
  2360.     READ_ROM(romAddr, infoPtr->vendor, 8);
  2361.     READ_ROM(romAddr, infoPtr->module, 8);
  2362.     READ_ROM(romAddr, infoPtr->type, 4);
  2363.     /*
  2364.      * Get rid of trailing spaces
  2365.      */
  2366.     for (i = 7; i >= 0; i--) {
  2367.     if (infoPtr->revision[i] == ' ') {
  2368.         infoPtr->revision[i] = '\0';
  2369.     }
  2370.     if (infoPtr->revision[i] != '\0') {
  2371.         break;
  2372.     } 
  2373.     }
  2374.     for (i = 7; i >= 0; i--) {
  2375.     if (infoPtr->vendor[i] == ' ') {
  2376.         infoPtr->vendor[i] = '\0';
  2377.     }
  2378.     if (infoPtr->vendor[i] != '\0') {
  2379.         break;
  2380.     } 
  2381.     }
  2382.     for (i = 7; i >= 0; i--) {
  2383.     if (infoPtr->module[i] == ' ') {
  2384.         infoPtr->module[i] = '\0';
  2385.     }
  2386.     if (infoPtr->module[i] != '\0') {
  2387.         break;
  2388.     } 
  2389.     }
  2390.     for (i = 3; i >= 0; i--) {
  2391.     if (infoPtr->type[i] == ' ') {
  2392.         infoPtr->type[i] = '\0';
  2393.     }
  2394.     if (infoPtr->type[i] != '\0') {
  2395.         break;
  2396.     } 
  2397.     }
  2398.     /*
  2399.      * Make sure all the strings are null terminated.
  2400.      */
  2401.     infoPtr->revision[8] = '\0';
  2402.     infoPtr->vendor[8] = '\0';
  2403.     infoPtr->module[8] = '\0';
  2404.     infoPtr->type[4] = '\0';
  2405.     return status;
  2406. }
  2407.  
  2408. /*
  2409.  *----------------------------------------------------------------------
  2410.  *
  2411.  * Mach_SigreturnStub --
  2412.  *
  2413.  *    Procedure to map from Unix sigreturn system call to Sprite.
  2414.  *    On the decstation, this is used for returning from a signal.
  2415.  *    Note: This routine is exactly the same as MachUNIXLongJumpReturn.
  2416.  *    Presumably the other routine will go away as soon as Unix
  2417.  *    compatibility is working.
  2418.  *
  2419.  * Results:
  2420.  *    Error code is returned upon error.  Otherwise SUCCESS is returned.
  2421.  *
  2422.  * Side effects:
  2423.  *    Side effects associated with the system call.
  2424.  *
  2425.  *----------------------------------------------------------------------
  2426.  */
  2427. int
  2428. Mach_SigreturnStub(sigContextPtr)
  2429.     struct sigcontext *sigContextPtr;
  2430. {
  2431.     struct sigcontext    sigContext;
  2432.     Mach_RegState    *regsPtr;
  2433.     ReturnStatus    status;
  2434.     extern Mach_State   *machCurStatePtr;
  2435.  
  2436.     status = Vm_CopyIn(sizeof(struct sigcontext), (Address)sigContextPtr,
  2437.                (Address)&sigContext);
  2438.     if (status != SUCCESS) {
  2439.     return(status);
  2440.     }
  2441.     regsPtr = &machCurStatePtr->userState.regState;
  2442.     regsPtr->pc = (Address)(sigContext.sc_pc - 4);
  2443.     bcopy(sigContext.sc_regs, regsPtr->regs, sizeof(sigContext.sc_regs));
  2444.     regsPtr->mflo = sigContext.sc_mdlo;
  2445.     regsPtr->mfhi = sigContext.sc_mdhi;
  2446.     bcopy(sigContext.sc_fpregs, regsPtr->fpRegs, sizeof(sigContext.sc_fpregs));
  2447.     regsPtr->fpStatusReg = sigContext.sc_fpc_csr;
  2448.     Proc_GetCurrentProc()->sigHoldMask = sigContext.sc_mask;
  2449.     return(SUCCESS);
  2450. }
  2451.  
  2452. /*
  2453.  *----------------------------------------------------------------------
  2454.  *
  2455.  * CheckFastRestart --
  2456.  *
  2457.  *    Check if enough space was allocated for the fast restart.
  2458.  *
  2459.  * Results:
  2460.  *    None.
  2461.  *
  2462.  * Side effects:
  2463.  *    None.
  2464.  *
  2465.  *----------------------------------------------------------------------
  2466.  */
  2467. static void
  2468. CheckFastRestart()
  2469. {
  2470.     /* No-op on decstations for now. */
  2471.     return;
  2472. }
  2473.  
  2474.  
  2475. /*
  2476.  *----------------------------------------------------------------------
  2477.  *
  2478.  * Mach_GetRestartTableSize --
  2479.  *
  2480.  *    Return the size allocated for the fast restart table area.
  2481.  *
  2482.  * Results:
  2483.  *    None.
  2484.  *
  2485.  * Side effects:
  2486.  *    None.
  2487.  *
  2488.  *----------------------------------------------------------------------
  2489.  */
  2490. int
  2491. Mach_GetRestartTableSize()
  2492. {
  2493.     /* No-op on decstations for now. */
  2494.     return 0;
  2495. }
  2496.  
  2497.  
  2498. /*
  2499.  *----------------------------------------------------------------------
  2500.  *
  2501.  * Mach_FastBoot --
  2502.  *
  2503.  *    Do a fast reboot (using copied initialized data heap, etc.)
  2504.  *
  2505.  * Results:
  2506.  *    FAILURE if we're not set up to do a fast boot.  Otherwise we don't
  2507.  *    return, but boot instead.
  2508.  *
  2509.  * Side effects:
  2510.  *    Will probably cause fast reboot.
  2511.  *
  2512.  *----------------------------------------------------------------------
  2513.  */
  2514. int
  2515. Mach_FastBoot()
  2516. {
  2517.     /* No-op on decstations for now. */
  2518.     Mach_MonPrintf("Can't do decstation fast boot yet.\n");
  2519.     return FAILURE;
  2520. }
  2521.